﻿/**
* Cache.js
* 
* @author Demis Bellot
* @version 1.0
* @requires Class.js, StringExt.js, ArrayExt.js 
* 
* Copyright 2009, Demis Bellot
* http://code.google.com/p/ajaxstack/
*/

function Cache(options, type)
{
	Cache.$baseConstructor.call(this);
	
	this.options =
	{
		size: 0,
		include: [],
		exclude: []
	};
	O.merge(this.options, options);

	this.log.debug("CACHE: init(): " + this.toString());

	this.count = 0;
	this.keys = [];
	this.data = {};
}
Cache.extend(ASObject, { type: "AjaxStack.Cache" }, {
	toString: function()
	{
		return S.toString(this.options.size, this.options.include, this.options.exclude);
	},

	getNextIndex: function()
	{
		return this.count++ % this.options.size;
	},

	isValidKey: function(key)
	{
		if (this.options.size == 0) return false;

		//ensure key is valid
		var include = this.options.include;
		if (!A.isEmpty(include)
			&& !A.any(include, function(i, s)
			{
				return S.startsWith(key, s);
			})
		) return false;

		//ensure key is not invalid
		var exclude = this.options.exclude;
		if (!A.isEmpty(exclude)
			&& !A.all(exclude, function(i, s)
			{
				return !S.startsWith(key, s);
			})
		) return false;

		return true;
	},

	add: function(key, value)
	{
		if (!this.isValidKey(key)) return;

		//this.log.debug("CACHE: adding valid key: " + key + ", ex: " + this.toString());

		if (this.data[key])
		{
			this.data[key] = value;
			return;
		}
		var i = this.getNextIndex();

		this.remove(i);

		this.keys[i] = key;

		this.data[key] = value;
	},

	remove: function(i)
	{
		var key = this.keys[i];
		if (!key) return;

		this.keys[i] = null;
		delete this.data[key];
	},

	getValue: function(key)
	{
		if (!this.isValidKey(key)) return;

		var value = this.data[key];

		this.log.debug("CACHE: getValue(): " + key + ": " + (value ? "HIT" : "MISS"));
		return value;
	}
}); 